package gu.sql2java;

import java.sql.ResultSet;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import gu.sql2java.exception.DaoException;
import gu.sql2java.exception.ObjectRetrievalException;
import gu.sql2java.exception.RuntimeDaoException;

/**
 * cache implementation for BaseTableManager<br>
 * @author guyadong
 */
class CacheManager extends BaseTableManager<BaseBean>
{
    /** instance of {@link TableCache} */
    private final TableCache<BaseBean> cache;
    CacheManager(String tablename,UpdateStrategy updateStrategy,Long maximumSize, Long duration, TimeUnit unit) {
        super(tablename);
        cache = new TableCache<>(metaData,updateStrategy,maximumSize,duration,unit);
        cache.registerListener();
    }
    CacheManager(String tablename){
    	this(tablename, null, null, null, null);
    }
    /**
     * create a instance of DeviceCacheManager and assign to {@link #instance} if {@code instance} is not initialized.<br>
     * otherwise return {@code instance}.
     * @param tablename
     * @param updateStrategy cache update strategy,{@link Constant#DEFAULT_STRATEGY} be used if {@code null}
     * @param maximumSize maximum capacity of cache ,{@link Constant#DEFAULT_CACHE_MAXIMUMSIZE } be used if {@code null} or <=0,see also {@link CacheBuilder#maximumSize(long)}
     * @param duration cache data expired time,{@link Constant#DEFAULT_DURATION} be used if {@code null} or <=0,see also {@link CacheBuilder#expireAfterAccess(long, TimeUnit)}
     * @param unit time unit for {@code duration},{@link Constant#DEFAULT_TIME_UNIT} be used if {@code null},see also {@link CacheBuilder#expireAfterAccess(long, TimeUnit)}
     */
    static synchronized final TableManager<?> makeCacheInstance(
    		String tablename,
    		UpdateStrategy updateStrategy,
    		long maximumSize, 
    		long duration, 
    		TimeUnit unit){
    	CacheManager manager = new CacheManager(tablename,updateStrategy,maximumSize,duration,unit);
    	return TableManagerDecorator.makeInterfaceInstance(manager);
    }
    @Override
    protected BaseBean doLoadByPrimaryKeyChecked(Object ...keys)throws RuntimeDaoException,ObjectRetrievalException{
        return cache.getBean(keys);
    }

    @Override
    protected boolean doExistsPrimaryKey(Object ...keys)throws RuntimeDaoException{
        return null != cache.getBeanUnchecked(keys);
    }
    
    @Override
    protected int actionOnResultSet(ResultSet rs, int[] fieldList, int startRow, int numRows, Action<BaseBean> action) throws DaoException{
        if(null == fieldList || fieldList.length == 0){
            action = cache.wrap(action);
        }
        return super.actionOnResultSet(rs, fieldList, startRow, numRows, action);
    }
    
    @Override
    protected BaseBean doLoadUniqueByIndex(String indexName,Object ...indexValues)throws RuntimeDaoException{
        return cache.getBeanByIndexUnchecked(indexName, indexValues);
    }
    
    @Override
    protected BaseBean doLoadUniqueByIndexChecked(String indexName,Object ...indexValues)throws ObjectRetrievalException{
        return cache.getBeanByIndex(indexName, indexValues);
    }
    
    @Override
    protected Map<String, TableListener<BaseBean>> getForeignKeyDeleteListeners(){
    	return cache.getManager().getForeignKeyDeleteListeners();
    }
    
    @Override
    public ListenerContainer<BaseBean> getListenerContainer() {
		return cache.getManager().getListenerContainer();
	}

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("CacheManager [cache=");
        builder.append(cache);
        builder.append("]");
        return builder.toString();
    }
}
